#include "SystemSDL_1_2.h"

#include "../Point.h"
#include "../Color.h"

#include <SDL.h>

union Test
{
    int cvar;

    struct
    {
        unsigned short pad;
        short carry;
    };
};

SDL_Surface* CSystemSDL_1_2_Renderer::m_pCurrentContext = NULL;

int CSystemSDL_1_2_Renderer::Init( void )
{
    m_pCurrentContext = SDL_GetVideoSurface();

    if( m_pCurrentContext == NULL )
    {
        printf( "Could not retieve video surface. %s\n", SDL_GetError() );
        return -1;
    }

    return 0;
}

void CSystemSDL_1_2_Renderer::ShutDown( void )
{
    if( m_pCurrentContext != NULL )
        m_pCurrentContext = NULL;
}

int CSystemSDL_1_2_Renderer::DrawPoint( const CPoint& pt, const CColor& color )
{
    unsigned int* pix = SDL_static_cast( unsigned int*, m_pCurrentContext->pixels );
    void* ptr = SDL_static_cast( void*, pix + pt.GetY() * m_pCurrentContext->w + pt.GetX() );

    SDL_memcpy( ptr, &color, sizeof( CColor ) );

    return 0;
}

int CSystemSDL_1_2_Renderer::DrawLine( const CPoint& begin, const CPoint& end, const CColor& color )
{
    //  BASED ON:   http://www.crbond.com/papers/newline.pdf

    Test t;
    t.cvar = 0x8000;

    // axis representation
    int minor = 0;              // minor axis, incremented by cvars overflow
    int major = 0;              // major axis, gets stepped along every iteration
    int step = 1;               // direction the line is drawn, either 1 0f -1
    int stop = 0;               // stop condition for the main loop
    int incr = 0;               // value to increment the minor axis by
    float slope = 0.0f;         // slope of the line

    // create local access
    int x1 = begin.GetX();
    int y1 = begin.GetY();
    int x2 = end.GetX();
    int y2 = end.GetY();

    int dx = x2 - x1;
    int dy = y2 - y1;

    // needed pointers
    int* x, *y = NULL;          // the plotting pointers
    unsigned int* pix = NULL;   // pointer to the pixel being written to
    int loc = 0;                // location of said pixel

    pix = SDL_static_cast( unsigned int*, m_pCurrentContext->pixels );

    if(  SDL_abs( dx ) > SDL_abs( dy ) )
    {
        slope = SDL_static_cast( float, SDL_abs( dy ) ) / SDL_static_cast( float, SDL_abs( dx ) );
        unsigned short temp = slope * 65536;
        incr = temp;

        // x is the major axis
        major = x1;
        minor = y1;
        stop = x2;

        // initialize the plotting pointers
        x = &major;
        y = &minor;

        if( dx < 0 )
        {
            // line is stepped the the left
            step = -1;
        }
        if( dy < 0 )
        {
            incr = -incr;
        }
    }
    else
    {
        slope = SDL_static_cast( float, SDL_abs( dx ) ) / SDL_static_cast( float, SDL_abs( dy ) );
        unsigned short temp = slope * 65536;
        incr = temp;
        // y is the major axis
        major = y1;
        minor = x1;
        stop = y2;

        // initilize the plotting pointers
        x = &minor;
        y = &major;

        if( dy < 0 )
        {
            step = -1;
        }
        if( dx < 0 )
        {
            incr = -incr;
        }
    }

    while( major != stop )
    {
        loc = *y * m_pCurrentContext->w + *x;
        SDL_memcpy( pix + loc, &color, sizeof( CColor ) );

        t.cvar += incr;
        minor += t.carry;
        major += step;

        t.carry = 0;
    }

    return 0;
}
